<template>
  <textarea ref="_textarea" :placeholder="placeholder"></textarea>
</template>
<script>
import _ from 'lodash'
// codemirror基础资源引入
import CodeMirror from "codemirror";
import "codemirror/lib/codemirror.css";
import "codemirror/mode/sql/sql.js";

// 折叠资源引入:开始
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/hint/show-hint.css";
// 折叠资源引入:结束

// 搜索资源引入:开始
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/match-highlighter.js";
import "codemirror/addon/search/jump-to-line.js";

import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
// 搜索资源引入:结束

import "codemirror/addon/hint/show-hint.js"
import "codemirror/addon/hint/sql-hint.js"

// 启用placeholder
import "codemirror/addon/display/placeholder.js";
//光标行背景高亮，配置里面也需要styleActiveLine设置为true
import "codemirror/addon/selection/active-line.js";

const AutoCompleteKeyword = ['from', 'join']

export default {
  props: {
    modelValue: String,
    defaultValue: String,
    placeholder: {
      type: String,
      default: '请输入'
    },
    readonly: {
      type: Boolean,
      default: false
    },
  },
  emits: [
    'update:modelValue',
  ],
  data() {
    return {
      editor: undefined,
    }
  },
  mounted() {
    this.init()
  },
  beforeUnmount() {
    if (this.editor != null) {
      this.editor.toTextArea();
      this.editor = null;
    }
  },
  methods: {
    init() {
      this.editor = CodeMirror.fromTextArea(this.$refs._textarea, {
        value: this.modelValue,
        mode: 'sql',
        // 在缩进时，是否需要把 n*tab宽度个空格替换成n个tab字符，默认为false
        indentWithTabs: false,
        // 自动缩进，设置是否根据上下文自动缩进（和上一行相同的缩进量）。默认为true
        smartIndent: true,
        // 是否在编辑器左侧显示行号
        lineNumbers: true,
        // 括号匹配
        matchBrackets: true,
        readOnly: this.readonly,
        // 启用代码折叠相关功能:开始
        foldGutter: true,
        lineWrapping: true,
        // 启用代码折叠相关功能
        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
        // 光标行高亮
        styleActiveLine: true,
        // 代码提示
        hintOptions: {
          completeSingle: false,
          tables: [
            // "table1": ["col_A", "col_B", "col_C"],
            {
              text: 'table1',
              displayText: 'table1 表格1',
              columns: [
                {text: "col_A", displayText: '字段A'},
                {text: "col_B", displayText: "字段B"},
                {text: "col_C", displayText: "字段C"},
              ]
            },
            {
              text: "table2",
              columns: ["other_columns1", "other_columns2"]
            },
          ],
        },
        extraKeys: {
          "Shift-Ctrl-F": function (cm) {
            console.log('format code!')
          },
          "Space": (cm) => {
            const cursor = cm.getCursor()
            const token = cm.getTokenAt(cursor)
            const currentWord = token.string

            // currentWord 转换成小写如果是 from/join 就弹出代码提示
            if (_.includes(AutoCompleteKeyword, _.toLower(currentWord))) {
              _.defer(() => {
                cm.showHint();
              })
            }

            return CodeMirror.Pass;
          },
          "'.'": (cm) => {
            _.defer(() => {
              cm.showHint();
            })
            return CodeMirror.Pass;
          },
        },
      });
      window['$editor'] = this.editor

      // 监听编辑器的ESC按键
      this.editor.on("keydown", (cm, event) => {
        if (event.keyCode === 27) {
          this.editor.closeHint();
        }
      });

      // 监听编辑器的change事件
      this.editor.on("change", () => {
        // 触发v-model的双向绑定
        this.$emit("update:modelValue", this.editor.getValue());
      });
      this.editor.on("cursorActivity", (cm) => {
        // console.log(cm)
        // this.editor.showHint();
      });
      // this.editor.on("inputRead", () => {
      //   this.editor.showHint();
      // });
      if (this.defaultValue) {
        this.editor.setValue(this.defaultValue);
      }
    }
  },
  computed: {}
  ,
  watch: {
    modelValue: {
      handler(newValue) {
        if (this.editor && typeof newValue === 'string' && newValue !== this.editor.getValue()) {
          // 触发v-model的双向绑定
          this.editor.setValue(newValue);
        }
      },
    },
    readonly: {
      handler(val) {
        if (this.editor) {
          this.editor.setOption("readOnly", val);
        }
      },
    }
  }
}
</script>